/*
ZhouSolver.h
Based on code posted to <http://forum.enjoysudoku.com/3-77us-solver-2-8g-cpu-testcase-17sodoku-t30470.html>
by user zhouyundong_2012.
The copyright is not specified.

this is a remorphing of the code to work in recursive mode
funtions have been added to work in generation mode
*/


/* the BIT_SET_30 pattern is defined in a band for a digit
   it is a map of candidates plus 3 bits for unsolved rows
   bits 0-8 9-17 18-26 for the rows 27-29 for unsolved rows
*/
class PM_GO;
class GAME{
	struct GLOBAL { // global variables for the game table
		int nsol,lim,a,b,c,na,nb,nc,
			F_or[27],// floor and multi floor process
			nfloors,
			onlyone; 
		USHORT * ptcor;
		GAME * mytable;
		char * zsol;
//		PM_GO * pgo;
		PMBF elims;
		word floors;
		int diagsource;
		GLOBAL();
	};
public:
	static GLOBAL glb;
	word index;
    int  BlockMaskSum[3],
		 F[27], //30-bit Full Mask
		 CompF[27],
		 BlockMask[27];

	void InitSudoku(const char * ze,int indexe=0);
	int Update();
	int UpdateMultiFloors();
	int UpdateExo();
	int UpdateFloor(int a,int b,int c);
	void Guess();
	void GuessFloor(int a,int b,int c);
	int GuessExo();
	void Guess(int ibf,int irow); 
	void GuessFloor(int ibf,int irow); 
	void GuessMulti();
	void GuessMulti(int ibf,int irow); 
	int  GuessExo(int ibf,int cell); 
	void Seta(int digit,int cell);
	void SetaFloor(int digit,int cell);
	void SetaMulti(int ibf,int cell);
	inline void ComputeNext (){if(Update())Guess();}
	void SetKnown(char * zs);
	// added for debugging purpose or generation steps
	int CheckValidityQuick(char * ze,int igame=0);
	int CheckValiditySolver(char * ze,int igame=0);
	int DoUpdate();// Update and test if finished
	word GetFreeDigits(int cell);

	void Band_to_Myd(PM_DATA & myd);
	void StdClean(int dig , int cell );
	void StdClean(int x) {StdClean(x>>7,x & 0x7f);}
	int Pointing17();
	int Pointing26();
	int Fupdate(int X,int ibl);
	int  UpdateCycle(int onlyone=0); // solving mode all possible moves
	word Go_One_Floor10();
};

